Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Commit a20f380284a728fa704fd16bc4504200eb386ece


Parents : 6d83b01
Author : Mark Qvist <mark@unsigned.io>
Date : 2024-09-08T14:52:54+02:00

Get message ratchet IDs

Changes

2 files changed, 38 insertions(+), 9 deletions(-)


Diff

diff --git a/LXMF/LXMRouter.py b/LXMF/LXMRouter.py
index 49793cb..659c47b 100644
--- a/LXMF/LXMRouter.py
+++ b/LXMF/LXMRouter.py
@@ -1260,9 +1260,14 @@ class LXMRouter:
### Message Routing & Delivery ########################
#######################################################
- def lxmf_delivery(self, lxmf_data, destination_type = None, phy_stats = None):
+ def lxmf_delivery(self, lxmf_data, destination_type = None, phy_stats = None, ratchet_id = None, method = None):
try:
message = LXMessage.unpack_from_bytes(lxmf_data)
+ if ratchet_id and not message.ratchet_id:
+ message.ratchet_id = ratchet_id
+
+ if method:
+ message.method = method
if message.signature_validated and FIELD_TICKET in message.fields:
ticket_entry = message.fields[FIELD_TICKET]
@@ -1299,6 +1304,7 @@ class LXMRouter:
if "snr" in phy_stats: message.snr = phy_stats["snr"]
if "q" in phy_stats: message.q = phy_stats["q"]
+ # TODO: Update these descriptions to account for ratchets
if destination_type == RNS.Destination.SINGLE:
message.transport_encrypted = True
message.transport_encryption = LXMessage.ENCRYPTION_DESCRIPTION_EC
@@ -1339,11 +1345,14 @@ class LXMRouter:
def delivery_packet(self, data, packet):
packet.prove()
try:
+ method = None
if packet.destination_type != RNS.Destination.LINK:
+ method = LXMessage.OPPORTUNISTIC
lxmf_data = b""
lxmf_data += packet.destination.hash
lxmf_data += data
else:
+ method = LXMessage.DIRECT
lxmf_data = data
try:
@@ -1356,7 +1365,7 @@ class LXMRouter:
phy_stats = {"rssi": packet.rssi, "snr": packet.snr, "q": packet.q}
- self.lxmf_delivery(lxmf_data, packet.destination_type, phy_stats=phy_stats)
+ self.lxmf_delivery(lxmf_data, packet.destination_type, phy_stats=phy_stats, ratchet_id=packet.ratchet_id, method=method)
except Exception as e:
RNS.log("Exception occurred while parsing incoming LXMF data.", RNS.LOG_ERROR)
@@ -1388,8 +1397,12 @@ class LXMRouter:
def delivery_resource_concluded(self, resource):
RNS.log("Transfer concluded for LXMF delivery resource "+str(resource), RNS.LOG_DEBUG)
if resource.status == RNS.Resource.COMPLETE:
+ ratchet_id = None
+ # Set ratchet ID to link ID if available
+ if resource.link and hasattr(resource.link, "link_id"):
+ ratchet_id = resource.link.link_id
phy_stats = {"rssi": resource.link.rssi, "snr": resource.link.snr, "q": resource.link.q}
- self.lxmf_delivery(resource.data.read(), resource.link.type, phy_stats=phy_stats)
+ self.lxmf_delivery(resource.data.read(), resource.link.type, phy_stats=phy_stats, ratchet_id=ratchet_id, method=LXMessage.DIRECT)
### Peer Sync & Propagation ###########################
@@ -1598,7 +1611,7 @@ class LXMRouter:
decrypted_lxmf_data = delivery_destination.decrypt(encrypted_lxmf_data)
if decrypted_lxmf_data != None:
delivery_data = lxmf_data[:LXMessage.DESTINATION_LENGTH]+decrypted_lxmf_data
- self.lxmf_delivery(delivery_data, delivery_destination.type)
+ self.lxmf_delivery(delivery_data, delivery_destination.type, ratchet_id=delivery_destination.latest_ratchet_id, method=LXMessage.PROPAGATED)
self.locally_delivered_transient_ids[transient_id] = time.time()
if signal_local_delivery != None:

diff --git a/LXMF/LXMessage.py b/LXMF/LXMessage.py
index adbac64..a41560f 100644
--- a/LXMF/LXMessage.py
+++ b/LXMF/LXMessage.py
@@ -159,6 +159,7 @@ class LXMessage:
self.incoming = False
self.signature_validated = False
self.unverified_reason = None
+ self.ratchet_id = None
self.representation = LXMessage.UNKNOWN
self.desired_method = desired_method
@@ -310,11 +311,13 @@ class LXMessage:
# generating a valid stamp.
if self.outbound_ticket != None and type(self.outbound_ticket) == bytes and len(self.outbound_ticket) == LXMessage.TICKET_LENGTH:
RNS.log(f"Generating stamp with outbound ticket for {self}", RNS.LOG_DEBUG) # TODO: Remove at some point
+ self.stamp_value = LXMessage.COST_TICKET
return RNS.Identity.truncated_hash(self.outbound_ticket+self.message_id)
# If no stamp cost is required, we can just
# return immediately.
elif self.stamp_cost == None:
+ self.stamp_value = None
return None
# If a stamp was already generated, return
@@ -504,6 +507,9 @@ class LXMessage:
RNS.log(f"Stamp generated in {RNS.prettytime(duration)}, {rounds} rounds, {int(speed)} rounds per second", RNS.LOG_DEBUG)
+ self.stamp_value = LXMessage.stamp_value(RNS.Identity.full_hash(workblock+stamp))
+ self.stamp_valid = True
+
return stamp
def pack(self):
@@ -575,6 +581,7 @@ class LXMessage:
single_packet_content_limit = LXMessage.LINK_PACKET_MAX_CONTENT
encrypted_data = self.__destination.encrypt(self.packed[LXMessage.DESTINATION_LENGTH:])
+ self.ratchet_id = self.__destination.latest_ratchet_id
self.propagation_packed = msgpack.packb([time.time(), [self.packed[:LXMessage.DESTINATION_LENGTH]+encrypted_data]])
content_size = len(self.propagation_packed)
@@ -589,6 +596,7 @@ class LXMessage:
paper_content_limit = LXMessage.PAPER_MDU
encrypted_data = self.__destination.encrypt(self.packed[LXMessage.DESTINATION_LENGTH:])
+ self.ratchet_id = self.__destination.latest_ratchet_id
self.paper_packed = self.packed[:LXMessage.DESTINATION_LENGTH]+encrypted_data
content_size = len(self.paper_packed)
@@ -605,14 +613,18 @@ class LXMessage:
self.determine_transport_encryption()
if self.method == LXMessage.OPPORTUNISTIC:
- self.__as_packet().send().set_delivery_callback(self.__mark_delivered)
+ lxm_packet = self.__as_packet()
+ lxm_packet.send().set_delivery_callback(self.__mark_delivered)
+ self.ratchet_id = lxm_packet.ratchet_id
self.state = LXMessage.SENT
elif self.method == LXMessage.DIRECT:
self.state = LXMessage.SENDING
if self.representation == LXMessage.PACKET:
- receipt = self.__as_packet().send()
+ lxm_packet = self.__as_packet()
+ receipt = lxm_packet.send()
+ self.ratchet_id = self.__delivery_destination.link_id
if receipt:
receipt.set_delivery_callback(self.__mark_delivered)
receipt.set_timeout_callback(self.__link_packet_timed_out)
@@ -623,6 +635,7 @@ class LXMessage:
elif self.representation == LXMessage.RESOURCE:
self.resource_representation = self.__as_resource()
+ self.ratchet_id = self.__delivery_destination.link_id
self.progress = 0.10
elif self.method == LXMessage.PROPAGATED:
@@ -692,7 +705,8 @@ class LXMessage:
try:
self.__delivery_callback(self)
except Exception as e:
- RNS.log("An error occurred in the external delivery callback for "+str(message), RNS.LOG_ERROR)
+ RNS.log("An error occurred in the external delivery callback for "+str(self), RNS.LOG_ERROR)
+ RNS.trace_exception(e)
def __mark_propagated(self, receipt = None):
RNS.log("Received propagation success notification for "+str(self), RNS.LOG_DEBUG)
@@ -703,7 +717,8 @@ class LXMessage:
try:
self.__delivery_callback(self)
except Exception as e:
- RNS.log("An error occurred in the external delivery callback for "+str(message), RNS.LOG_ERROR)
+ RNS.log("An error occurred in the external delivery callback for "+str(self), RNS.LOG_ERROR)
+ RNS.trace_exception(e)
def __mark_paper_generated(self, receipt = None):
RNS.log("Paper message generation succeeded for "+str(self), RNS.LOG_DEBUG)
@@ -714,7 +729,8 @@ class LXMessage:
try:
self.__delivery_callback(self)
except Exception as e:
- RNS.log("An error occurred in the external delivery callback for "+str(message), RNS.LOG_ERROR)
+ RNS.log("An error occurred in the external delivery callback for "+str(self), RNS.LOG_ERROR)
+ RNS.trace_exception(e)
def __resource_concluded(self, resource):
if resource.status == RNS.Resource.COMPLETE:


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────